package cn.turboinfo.dongying.api.gateway.admin.framework.http.interceptor

import cn.turboinfo.dongying.api.entity.admin.exception.user.SysUserNotLoginException
import cn.turboinfo.dongying.api.gateway.admin.framework.http.context.AdminRequestContextHolder
import cn.turboinfo.dongying.api.gateway.web.framework.http.annotation.PermissionScope
import cn.turboinfo.dongying.api.gateway.web.framework.http.interceptor.BaseHandlerInterceptorAdapter
import mu.KotlinLogging
import nxcloud.ext.springmvc.automapping.spring.AutoMappingRequestParameterTypeBinding
import org.apache.shiro.SecurityUtils
import org.apache.shiro.authz.UnauthorizedException
import org.springframework.stereotype.Component
import org.springframework.web.method.HandlerMethod
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import kotlin.jvm.optionals.getOrNull

@Component
class AdminPermissionScopeInterceptor(
    private val autoMappingRequestParameterTypeBinding: AutoMappingRequestParameterTypeBinding,
    private val adminSessionHelper: cn.turboinfo.dongying.api.provider.admin.component.session.AdminSessionHelper,
) : BaseHandlerInterceptorAdapter() {

    private val logger = KotlinLogging.logger {}

    @OptIn(ExperimentalStdlibApi::class)
    override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
        if (handler is HandlerMethod) {
            val annotation = getAnnotation(
                handler,
                PermissionScope::class.java,
                true
            ).getOrNull()
                ?: autoMappingRequestParameterTypeBinding.getAnnotation(
                    handler.method,
                    PermissionScope::class.java,
                    true
                )
                ?: return true

            val requestContext =
                AdminRequestContextHolder.current()

            if (!requestContext.isLogin) {
                throw SysUserNotLoginException("系统用户未登录")
            }

            val subject = SecurityUtils.getSubject()
            if (annotation.value
                    .none {
                        subject.isPermitted(it)
                    }
            ) {
                throw UnauthorizedException("没有权限执行当前的操作")
            }
        }

        return true
    }
}